package com.taglab.chic.atom.syndication.spring;

import com.taglab.chic.atom.AtomEntry;
import com.taglab.chic.atom.AtomFeed;
import com.taglab.chic.atom.syndication.AtomFeedWriter;
import org.springframework.beans.BeansException;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.view.AbstractView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author Markus Kobler
 */
public class AtomView extends AbstractView {

  private String encoding = "UTF-8";

  private String atomFeedKey;
  private String atomEntriesKey;
  private AtomFeed atomFeedTemplate;

  private boolean customContentTypeSet = false;

  public String getEncoding() {
    return encoding;
  }

  public void setEncoding(String encoding) {
    this.encoding = encoding;
  }

  public void setAtomFeedKey(String atomFeedKey) {
    this.atomFeedKey = atomFeedKey;
  }

  public void setAtomEntriesKey(String atomEntriesKey) {
    this.atomEntriesKey = atomEntriesKey;
  }

  public void setAtomFeedTemplate(AtomFeed atomFeedTemplate) {
    this.atomFeedTemplate = atomFeedTemplate;
  }

  @Override
  public void setContentType(String contentType) {
    super.setContentType(contentType);
    customContentTypeSet = true;
  }

  @Override
  public String getContentType() {
    if( customContentTypeSet ) {
      return super.getContentType();      
    } else {
      return "application/atom+xml;charset=\""+getEncoding()+"\"";
    }
  }

  protected void renderMergedOutputModel(Map model,
                                         HttpServletRequest request,
                                         HttpServletResponse response) throws Exception {

    response.setCharacterEncoding(getEncoding());
    response.setContentType(getContentType());

    AtomFeedWriter writer = new AtomFeedWriter(response.getOutputStream(), getEncoding());

    AtomFeed feed = locateAtomFeed(model);

    if( feed != null ) {
      
      writer.write(feed);

    } else {

      if( atomFeedTemplate == null ) throw new IllegalStateException("AtomFeed not found in model and no template set");

      Iterable<AtomEntry> entries = locateAtomEntries(model);

      if( entries == null ) throw new IllegalArgumentException("Could not find atom feed or entires");

      writer.write(atomFeedTemplate, entries );
      
    }

  }

  protected AtomFeed locateAtomFeed(Map model) throws Exception {
    if (this.atomFeedKey != null) {
      return (AtomFeed)model.get(this.atomFeedKey);
    }    
    return (AtomFeed)CollectionUtils.findValueOfType(model.values(), AtomFeed.class);
  }

  protected Iterable<AtomEntry> locateAtomEntries(Map model) throws Exception {
    
    if (this.atomEntriesKey != null) {
      return (Iterable<AtomEntry>)model.get(this.atomEntriesKey);
    }

    List<AtomEntry> entries = null;
    for( Object value : model.values() ) {
      if( value instanceof AtomEntry ) {
        if( entries == null ) entries = new ArrayList<AtomEntry>();
        entries.add((AtomEntry)value);
      } else if( value instanceof AtomEntry[]) {
        if( entries == null ) {
          entries = Arrays.asList((AtomEntry[])value);
        } else {
          entries.addAll(Arrays.asList((AtomEntry[])value));
        }
      }
    }

    return entries;
  }


}
